﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Windows;
using Caliburn.Micro;
using PurchaseSales.Manage.Common.AOP;
using PurchaseSales.Manage.Common.Extensions;
using PurchaseSales.Manage.Model.Entities;
using PurchaseSales.Manage.Services;
using PurchaseSales.Manage.Views.UserControls;
using ReactiveUI;
using ReactiveUI.Xaml;

namespace PurchaseSales.Manage.ViewModels
{
    public class SupplierViewModel : Screen
    {
        private readonly ISupplierRepository _repository;
        private readonly IWindowManager _windowManager;

        public ReactiveAsyncCommand SelectedSupplierrCommand { get; set; }
        public ReactiveAsyncCommand AddCommand { get; set; }
        public ReactiveAsyncCommand RemoveCommand { get; set; }
        public ReactiveAsyncCommand EditCommand { get; set; }
        public ReactiveAsyncCommand LoadCommand { get; set; }
        private ObservableAsPropertyHelper<ReactiveCollection<Supplier>> _suppliers;
        private ObservableAsPropertyHelper<Supplier> _selectedSupplier;

        public SupplierViewModel(ISupplierRepository repository, IWindowManager windowManager)
        {
            _repository = repository;
            _windowManager = windowManager;

            LoadCommand = new ReactiveAsyncCommand();
            var observable = LoadCommand.RegisterAsyncFunction(_ =>
            {
                var suppliers = _repository.GetAll();
                return suppliers.ToObservable().CreateCollection();
            });
            _suppliers = new ObservableAsPropertyHelper<ReactiveCollection<Supplier>>(observable, _ =>
            {
                NotifyOfPropertyChange(() => Suppliers);
            });
            SelectedSupplierrCommand = new ReactiveAsyncCommand();
            var @select = SelectedSupplierrCommand.Select(o => o as Supplier);
            _selectedSupplier = new ObservableAsPropertyHelper<Supplier>(@select, _ => { });
            AddCommand = new ReactiveAsyncCommand();
            AddCommand.Subscribe(o =>
                                     {
                                         var supplier = DataBindingFactory.Create<Supplier>();
                                         var dialogViewModel = IoC.Get<IShowDialogViewModel<Supplier>>();
                                         dialogViewModel.ShowDialogContent = new AddSupplier();
                                         dialogViewModel.Entity = supplier;
                                         CanConfirm = dialogViewModel.CanConfirm;
                                         NotifyEntityChanged(supplier);
                                         var showDialog = _windowManager.ShowDialog(dialogViewModel);
                                         if (showDialog == true)
                                         {
                                             Suppliers.Add(dialogViewModel.Entity);
                                             _repository.Save(dialogViewModel.Entity);
                                         }
                                     });
            RemoveCommand = new ReactiveAsyncCommand(_selectedSupplier.Select(x => x != null).StartWith(false));
            RemoveCommand.Subscribe(o =>
            {
                _repository.MakeTransient(SelectedSupplier);
                Suppliers.Remove(SelectedSupplier);
                _repository.Commit();
            });
            RemoveCommand.ThrownExceptions.Subscribe(_ => MessageBox.Show("Remove Error"));

            EditCommand = new ReactiveAsyncCommand(_selectedSupplier.Select(x => x != null).ObserveOnDispatcher().StartWith(false));
            EditCommand.Subscribe(o =>
            {
                var dialogViewModel = IoC.Get<IShowDialogViewModel<Supplier>>();
                dialogViewModel.ShowDialogContent = new AddSupplier();
                dialogViewModel.Entity = SelectedSupplier;
                CanConfirm = dialogViewModel.CanConfirm;
                NotifyEntityChanged(SelectedSupplier);
                var showDialog = _windowManager.ShowDialog(dialogViewModel);
                if (showDialog == true)
                {
                    _repository.Save(dialogViewModel.Entity);
                }
                else
                {
                    _repository.Evict(dialogViewModel.Entity);
                    LoadCommand.Execute(this);
                }
            });


        }

        public Supplier SelectedSupplier
        {
            get { return _selectedSupplier.Value; }
        }

        public ReactiveCollection<Supplier> Suppliers
        {
            get { return _suppliers.Value; }
        }

        public Action<bool> CanConfirm;
        public bool CanSave(Supplier supplier)
        {
            return !string.IsNullOrEmpty(supplier.Number) && !string.IsNullOrEmpty(supplier.Name);

        }
        private void NotifyEntityChanged(Supplier supplier)
        {
            var entity = supplier as INotifyPropertyChanged;
            entity.SafeInvoke(x => x.PropertyChanged += (sender, args) =>
            {
                CanConfirm.Invoke(CanSave(supplier));
            });
        }
    }
}
